//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1999  Microsoft Corporation

Module Name:

comhand.h

Abstract:


Notes:


--*/
/*
------------------------------------------------------------------------------
    Revision History
    Date                Author            Activity ID            Activity Headline
    2007-04-26          qinxuetao         WM600002433            Add critical section m_csDownstream
    2007-05-10          qinxuetao         WM600002914            Delay Dial commands to wait for radio to settle
    2007-06-21          qinxuetao         WM600007125            Change STK and PB init procedure
------------------------------------------------------------------------------
*/

#pragma once



//
// Defines
//

#define STAT_BUCKETS                10
#define STAT_BUCKET_WEIGHTS         (STAT_BUCKETS * (STAT_BUCKETS + 1) / 2)


//
// Forward declarations
//
class CComInstanceHandle;


//
// Virtual serial device handle
//
class CComHandle : public CSharedResource
{
public:
                CComHandle();
                ~CComHandle();

    BOOL        Init();
    BOOL        OpenDownstreamPort();
    BOOL        CloseDownstreamPort();
    BOOL        Read(void* pBuf, const UINT cb, DWORD& rdwRead) const;
#ifdef OEM2_DRIVER
    BOOL        Read2(void* pBuf, const UINT cb, DWORD& rdwRead) const;
#endif // OEM2_DRIVER
    BOOL        Write(const void* pBuf, const UINT cb, DWORD& rdwWritten) const;
    BOOL        IOControl(const DWORD dwCode, const BYTE* const pBufIn, const DWORD dwLenIn, BYTE* const pBufOut,
                          const DWORD dwLenOut, DWORD& rdwActualOut) const;
    BOOL        WriteCharsToComPort(CRilHandle* const pRilDevice, LPCSTR szChars, UINT cbToWrite);
    BOOL        WriteCmdsToComPort (CRilHandle* const pRilDevice, LPCSTR szChars, UINT cbToWrite);

    BOOL        WaitCommEventWithTimeout(DWORD dwTimeout, DWORD& rdwMask);
    BOOL        SendRILCmdHandleRsp(CRilHandle* const pRilDevice, CCommand*& rpCmd, BOOL& rfHungUp, BOOL& rfTimedOut);
    BOOL        SendRILCmdsInDataMode(CRilHandle* const pRilDevice, BOOL& rfBackToCmdMode);
#ifdef OEM1_DRIVER
    BOOL        WaitForRadioSignon(CRilHandle* const pRilDevice);
#endif // OEM1_DRIVER
    BOOL        EnterDataMode(const LPCSTR szData, const UINT cbData);
    BOOL        ExitDataMode();
    BOOL        FDataMode();
    BOOL        WaitForCommandMode() const;
    BOOL        FEnoughTimeToSendCmd(CCommand* pCmd, DWORD dwTimeLeft) const;
    UINT        ReadFromBackupBuffer(void* const pDestination, const DWORD cbToRead);
    BOOL        InitComPortForRIL(DCB* const pdcbOld, COMMTIMEOUTS* const pctOld) const;
    BOOL        GetDTRDropResponse(CRilHandle* const pRilDevice);
    BOOL        FPortOpened() const                 { return m_fPortOpened; };
    CBuffer*    GetBackupBuffer() const             { return m_pBuffer; };
    BOOL        SetOwner(const CComInstanceHandle* const pHandle);
    BOOL        ClearOwner(const CComInstanceHandle* const pOwner);
    BOOL        FHandleIsOwner(const CComInstanceHandle* const pHandle)
                                                    { SYNCBLOCK(m_csOwner); return (pHandle == m_pOwner); };
#ifndef DEDICATED_DATA_PORT
        BOOL        FDataModeInterrupted();
        void        ResetDataModeInterrupted();
#endif
    void        UpdateComStatData(const BOOL fRead, const DWORD dwBytes);
    void        CalculateComStats(DWORD& rdwReadBitsPerSec, DWORD& rdwWrittenBitsPerSec);
    DWORD       CalculateCmdModeTime();
    void        SetCancelledDial() { m_fCancelledDial = TRUE; }

    BOOL        VirtWaitCommEvent(DWORD* const pdwMask) const;
    BOOL        VirtClearCommBreak() const;
    BOOL        VirtClearCommError(DWORD* const pdwErrors, COMSTAT* const pcs) const;
    BOOL        VirtEscapeCommFunction(const DWORD dwFunc) const;
    BOOL        VirtGetCommMask(DWORD* const pdwMask) const;
    BOOL        VirtSetCommMask(const DWORD dwMask) const;
    BOOL        VirtGetCommModemStatus(DWORD* const pdwStatus) const;
    BOOL        VirtGetCommProperties(COMMPROP* const pcp) const;
    BOOL        VirtGetCommState(DCB* const pdcb) const;
    BOOL        VirtSetCommState(DCB* const pdcb) const;
    BOOL        VirtGetCommTimeouts(COMMTIMEOUTS* const pct) const;
    BOOL        VirtSetCommTimeouts(COMMTIMEOUTS* const pct) const;
    BOOL        VirtPurgeComm(const DWORD dwFlags) const;
    BOOL        VirtSetCommBreak() const;
    BOOL        VirtSetupComm(const DWORD dwInQueue, const DWORD dwOutQueue) const;
    BOOL        VirtTransmitCommChar(const char cChar) const;

    void        SetTimeoutStatus(BOOL bTimedOut);

    static void ResetCommMask(DWORD dwParam);
    BOOL        EnterExclusiveUse()
    {
        return CSharedResource::EnterExclusiveUse(ResetCommMask,(DWORD)m_hDownstream);
    }

    BOOL        InitCommState(DCB* const pdcbOld) const;

private:
    HANDLE                      m_hDownstream;
#ifdef OEM2_DRIVER
    HANDLE                      m_hDownstream2;
#endif
    HANDLE                      m_hCommandModeEvent;
    HANDLE                      m_hCancelEvent;
#ifndef DEDICATED_DATA_PORT
        HANDLE                      m_hDataModeInterrupted;
#endif
#ifdef DEDICATED_DATA_PORT
    HANDLE                      m_hDataModeEvent;
#endif
    CBuffer*                    m_pBuffer;
    DWORD                       m_dwDownstreamBaudRate;
    DWORD                       m_dwStatQuantum;
    DWORD                       m_rgdwReadStatBits[STAT_BUCKETS];
    DWORD                       m_rgdwWriteStatBits[STAT_BUCKETS];
    DWORD                       m_dwReadStatTimestamp;
    DWORD                       m_dwWriteStatTimestamp;
    const CComInstanceHandle*   m_pOwner;
    CRITICAL_SECTION            m_csDataMode;
    CRITICAL_SECTION            m_csOwner;
    CRITICAL_SECTION            m_csStats;
    CRITICAL_SECTION            m_csDownstream;
    DWORD                       m_fInited : 1;
    DWORD                       m_fPortOpened : 1;
    DWORD                       m_fDataMode : 1;
    DWORD                       m_fCancelledDial : 1;
    DWORD                       m_dwNumTimeouts;
    DWORD                       m_dwMaxTimeouts;
};



//
// Virtual serial instance handle
//
class CComInstanceHandle
{
public:
                        CComInstanceHandle();
                        ~CComInstanceHandle();

    BOOL                Init(CComHandle* const pDevice, const DWORD dwAccess);
    CComHandle*         GetDevice() const        { return m_pDevice; };

private:
    CComHandle*     m_pDevice;
};



//
// Parameter structure passed to WCETimeoutThread()
//
struct WCETIMEOUT_THREAD_DATA {
    DWORD dwTimeout;
    HANDLE hCancelEvent;
    HANDLE hPort;
};


//
// Parameter strcuture passed to HangupThreadProc
//
struct HANGUP_THREAD_DATA {
    HANDLE hQuitEvent;
    CComHandle* pComDevice;
    CRilHandle* pRilDevice;
};



//
// Functions
//
#ifndef UNDER_CE

//
// Operlapped operations
//
enum OVERLAPPED_OPER
{
    OVERLAPPED_WAIT = 1,
    OVERLAPPED_READ,
    OVERLAPPED_WRITE
};

BOOL PerformOverlappedIO(const OVERLAPPED_OPER oper, const HANDLE hCom, void* pbData, UINT cbData, DWORD* pdwData);

#endif // UNDER_CE

extern BOOL g_bRadioOff;
#ifdef WAVECOM_DRIVER
extern DWORD g_dwPhoneOn;
#endif
